# Replication script for "Incentives and Constraints: A Configurational Account of European Involvement
# in the anti-Daesh Coalition", European Political Science Review (2022),
# https://doi.org/10.1017/S1755773921000333
# A corrigendum has been issued for this article: https://doi.org/10.1017/S1755773922000091

# Author: Patrick A. Mello
# Website: https://patrickmello.com
# E-mail: mello@hfp.tum.de

# Load Packages
library(QCA); library(SetMethods); library(ggplot2); library(gridExtra)

# Read Data
coal <- read.csv("EPSR Mello raw and calibrated data.csv", header = TRUE, row.names = 1)
head(coal)

# Calibration
coal$T <- calibrate(coal$T_raw, type = "fuzzy", method = "direct", c(1, 2, 200), logistic = TRUE)
coal$T <- round(coal$T, 2)

coal$A <- calibrate(coal$A_raw, type = "fuzzy", method = "direct", c(0.75, 1.25, 2), logistic = TRUE)
coal$A <- round(coal$A, 2)

coal$R <- calibrate(coal$R_raw, type = "fuzzy", method = "direct", c(4, 5, 6), logistic = TRUE)
coal$R <- round(coal$R, 2)

coal$P <- calibrate(coal$P_raw, type = "fuzzy", method = "direct", c(0.5, 0.625, 0.7), logistic = TRUE)
coal$P <- round(coal$P, 2)

daesh <- coal[ , c("T","A","R","V","P","M")]

# Necessary Condition Analysis (Table 4)
NC <- QCAfit(daesh[, 1:5], daesh$M, necessity = TRUE)
NC

# Conservative Solution
TTcs <- truthTable(daesh, outcome = "M", conditions = "T,A,R,V,P", complete = FALSE, 
                    show.cases = TRUE, sort.by = c("incl", "n"), 
                    n.cut = 1, incl.cut = 0.80)
TTcs # (Table 5)

SOLcs <- minimize(TTcs, outcome = "M",include = "1", row.dom = FALSE, 
                  details = TRUE, show.cases = TRUE, 
                  use.tilde = TRUE, all.sol = TRUE, method = "CCubes")
SOLcs # (Table A3)

# Parsimonious Solution
TTps <- truthTable(daesh, outcome = "M", conditions = "T,A,R,V,P", 
                   complete = TRUE, show.cases = TRUE, 
                   sort.by = c("incl", "n"), n.cut = 1, incl.cut = 0.80)
TTps # (Table A2)

SOLps <- minimize(TTps, outcome = "M", include = "1, ?", 
                  row.dom = TRUE, details = TRUE,
                  use.tilde = TRUE, method = "CCubes")
SOLps # (Table A4)

# Intermediate Solution
SOLis <- minimize(TTps, outcome = "M", include = "?",
                  row.dom = TRUE, all.sol = TRUE, details = TRUE, 
                  show.cases = TRUE, use.tilde = TRUE, 
                  dir.exp = c(T,A,~V,P), method = "CCubes")
SOLis # (Table 1)

# Supplementary materials
# https://static.cambridge.org/content/id/urn:cambridge.org:id:article:S1755773921000333/resource/name/S1755773921000333sup001.docx

# Histograms (Figure A1)
par(mfrow = c(3, 2), lwd = 2)

h.T <- hist(daesh$T, freq = TRUE, col = "white", ylim = c(0, 20), xlim = c(0,1),
            xlab = "External Threat", ylab = "Frequency", font = 2, 
            breaks = c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1),
            font.lab = 2, main = "", lty = 1, lwd = 2, cex.lab = 1.1, cex.axis = 1.1)

h.A <- hist(daesh$A, freq = TRUE, col = "white", ylim = c(0, 20), xlim = c(0,1),
            xlab = "Alliance Value", ylab = "Frequency", font = 2, 
            breaks = c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1),
            font.lab = 2, main = "", lty = 1, lwd = 2, cex.lab = 1.1, cex.axis = 1.1)

h.R <- hist(daesh$R, freq = TRUE, col = "white", ylim = c(0, 20), xlim = c(0,1),
            xlab = "Right Executive", ylab = "Frequency", font = 2, 
            breaks = c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1),
            font.lab = 2, main = "", lty = 1, lwd = 2, cex.lab = 1.1, cex.axis = 1.1)

h.V <- hist(daesh$V, freq = TRUE, col = "white", ylim = c(0, 20), xlim = c(0,1),
            xlab = "Parliamentary Veto Rights", ylab = "Frequency", font = 2, 
            breaks = c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1),
            font.lab = 2, main = "", lty = 1, lwd = 2, cex.lab = 1.1, cex.axis = 1.1)

h.P <- hist(daesh$P, freq = TRUE, col = "white", ylim = c(0, 20), xlim = c(0,1),
            xlab = "Public Support", ylab = "Frequency", font = 2, 
            breaks = c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1),
            font.lab = 2, main = "", lty = 1, lwd = 2, cex.lab = 1.1, cex.axis = 1.1)

h.M <- hist(daesh$M, freq = TRUE, col = "white", ylim = c(0, 20), xlim = c(0,1),
             xlab = "Military Participation", ylab = "Frequency", font = 2, 
            breaks = c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1),
             font.lab = 2, main = "", lty = 1, lwd = 2, cex.lab = 1.1, cex.axis = 1.1)

# Robustness Tests

# Crisp-Set Analysis (Table A5)
daesh_cs <- round(daesh, 0)

TTcs_cs <- truthTable(daesh_cs, outcome = "M", conditions = "T,A,R,V,P", complete = TRUE, 
                      show.cases = TRUE, 
                      sort.by = c("incl", "n"), n.cut = 1, incl.cut = 0.8)

SOLis_cs <- minimize(TTcs_cs, outcome = "M", include = "?",
                  row.dom = TRUE, all.sol = TRUE, details = TRUE, 
                  show.cases = TRUE, use.tilde = TRUE, 
                  dir.exp = c(T,A,~V,P), method = "CCubes")
SOLis_cs

# Calibration thresholds (Table A1)
rob.calibrange(raw.data = coal, calib.data = coal,
               test.cond.raw = "T_raw", test.cond.calib = "T",
               test.thresholds = c(1, 2, 200), step = 1, max.runs = 10,
               outcome  = "M", conditions = c("T", "A", "R", "V", "P"),
               incl.cut = 0.8, n.cut = 1, include = "?")

rob.calibrange(raw.data = coal, calib.data = coal,
               test.cond.raw = "A_raw", test.cond.calib = "A",
               test.thresholds = c(0.75, 1.25, 2), step = 0.5, max.runs = 10,
               outcome  = "M", conditions = c("T", "A", "R", "V", "P"),
               incl.cut = 0.8, n.cut = 1, include = "?")

rob.calibrange(raw.data = coal, calib.data = coal,
               test.cond.raw = "R_raw", test.cond.calib = "R",
               test.thresholds = c(4, 5, 6), step = 0.5, max.runs = 10,
               outcome  = "M", conditions = c("T", "A", "R", "V", "P"),
               incl.cut = 0.8, n.cut = 1, include = "?")

rob.calibrange(raw.data = coal, calib.data = coal,
               test.cond.raw = "P_raw", test.cond.calib = "P",
               test.thresholds = c(0.50, 0.625, 0.70), step = 0.1, max.runs = 10,
               outcome  = "M", conditions = c("T", "A", "R", "V", "P"),
               incl.cut = 0.8, n.cut = 1, include = "?")

# Alternative Outcome (Table A6)
TTm2 <- truthTable(coal, outcome = "M_alternative", conditions = "T,A,R,V,P", complete = TRUE, show.cases = TRUE, 
                      sort.by = c("incl", "n"), n.cut = 1, incl.cut = 0.8)

SOLis_cs <- minimize(TTm2, outcome = "M_alternative", include = "?",
                     row.dom = TRUE, all.sol = TRUE, details = TRUE, 
                     show.cases = TRUE, use.tilde = TRUE, 
                     dir.exp = c(T,A,~V,P), method = "CCubes")
SOLis_cs

# Restricted analysis with 3 conditions (Table A7)
TTps <- truthTable(daesh, outcome = "M", conditions = "T,A,V", 
                   complete = TRUE, show.cases = TRUE, 
                   sort.by = c("incl", "n"), n.cut = 1, incl.cut = 0.80)

SOLis <- minimize(TTps, outcome = "M", include = "?",
                  row.dom = TRUE, all.sol = TRUE, details = TRUE, 
                  show.cases = TRUE, use.tilde = TRUE, 
                  dir.exp = c(T,A,~V), method = "CCubes")
SOLis

## End